﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Mogre;
using MogreNewt;

namespace eqgen
{
    class Character : GameObject
    {
        public enum CharacterState
        {
            IDLE,
            WALK
        };

        public Entity Entity;
        public SceneNode Node;
        public Body Body;

        public CharacterProfile Profile;
        public CharacterState State;

        public Quaternion Orientation;
        public Vector3 Velocity;

        public Character(CharacterProfile profile)
        {
            Profile = profile.Clone();
            Orientation = Quaternion.IDENTITY;
 
            Entity = Engine.Singleton.SceneManager.CreateEntity(Profile.MeshName);
            Node = Engine.Singleton.SceneManager.RootSceneNode.CreateChildSceneNode();
            Node.AttachObject(Entity);

            // Bierzemy połowę rozmiaru BoundingBoxa i mnożymy go przez czynnik
            Vector3 scaledSize = Entity.BoundingBox.HalfSize * Profile.BodyScaleFactor;
 
            ConvexCollision collision = new MogreNewt.CollisionPrimitives.Capsule(
                Engine.Singleton.NewtonWorld,
                // Wybieramy szerokość bądź długość
                System.Math.Min(scaledSize.x, scaledSize.z), 
                // Z uwagi na to, że wzięliśmy połowę rozmiaru, 
                // musimy wysokość pomnożyć przez 2
                scaledSize.y * 2, 
                // Kapsuła stworzona przez Newtona będzie leżeć wzdłuż osi X, 
                // więc ustalamy pion wzdłóż osi Y
                Vector3.UNIT_X.GetRotationTo(Vector3.UNIT_Y), 
                Engine.Singleton.GetUniqueBodyId()); // Unikalny identyfikator ciała

            Vector3 inertia, offset;
            collision.CalculateInertialMatrix(out inertia, out offset);
            inertia *= Profile.BodyMass;

            Body = new Body(Engine.Singleton.NewtonWorld, collision, true);
            Body.AttachNode(Node);
            Body.SetMassMatrix(Profile.BodyMass, inertia);            
            Body.AutoSleep = false; 
            Body.Transformed += BodyTransformCallback;
            Body.ForceCallback += BodyForceCallback;

            Joint upVector = new MogreNewt.BasicJoints.UpVector(Engine.Singleton.NewtonWorld, Body, Vector3.UNIT_Y);

            collision.Dispose();
        }

        void BodyTransformCallback(Body sender, Quaternion orientation, Vector3 position, int threadIndex)
        {
            Node.Position = position;
            Node.Orientation = Orientation;
        }

        public void BodyForceCallback(Body body, float timeStep, int threadIndex)
        {
            Vector3 force = (Velocity - Body.Velocity * new Vector3(1, 0, 1)) * Profile.BodyMass * 60.0f;
            Body.AddForce(force);
        }

        public void SetPosition(Vector3 position)
        {
            Body.SetPositionOrientation(position, Orientation);
        }

        public override void Update()
        {
            AnimationState idleAnimation = Entity.GetAnimationState("Idle");
            AnimationState walkAnimation = Entity.GetAnimationState("Walk");
            
            switch (State)
            {
            case CharacterState.IDLE:
                Velocity = Vector3.ZERO;
                walkAnimation.Enabled = false;
                idleAnimation.Enabled = true;
                idleAnimation.Loop = true;
                idleAnimation.AddTime(1.0f / 180.0f);
                break;
            case CharacterState.WALK:
                Velocity = Orientation * Vector3.UNIT_Z * Profile.WalkSpeed;
                idleAnimation.Enabled = false;
                walkAnimation.Enabled = true;
                walkAnimation.Loop = true;
                walkAnimation.AddTime(1.0f / 180.0f);
                break;
            }
        }

            
    }
}
